#pragma once

typedef struct _DNS_APPROVAL_OUTPUT
{
    DNS_APPROVAL_CONFIG  m_stApprovalConfig;
    BYTE                 m_pData[65536];
} DNS_APPROVAL_OUTPUT, *PDNS_APPROVAL_OUTPUT;

typedef struct _dns_question_record
{
    CString sQNAME;
    DNS_WIRE_QUESTION   stDnsWireQuestion;
}
dns_question_record;

inline bool IsPrivate(int nA4Count, int nA4PrivateCount, int nA6Count, int nA6PrivaiteCount)
{
    return (((nA4Count > 0) && (nA4Count == nA4PrivateCount) && (nA6Count == 0))
        || ((nA4Count == 0) && (nA6Count > 0) && (nA6Count == nA6PrivaiteCount))
        || ((nA4Count > 0) && (nA4Count == nA4PrivateCount) && (nA6Count > 0) && (nA6Count == nA6PrivaiteCount)));
}


// CDnsMessageWB command target
class CDnsResorceRecord;
class CDnsMessageWB
{
public:
	CDnsMessageWB();
	virtual ~CDnsMessageWB();
    DNS_HEADER m_stDnsHeader;
    CDnsResorceRecord* m_pFirstDnsRRecord;
    CDnsResorceRecord* m_pLastDnsRRecord;
    bool ParseDnsMessageBuffer(PDNS_MESSAGE_BUFFER pDnsMessageBufer, WORD wMessageLength);
    unsigned short m_nAnswerCount;
    unsigned short m_nNameServerCount;
    unsigned short m_nAdditionalCount;
    dns_question_record m_stDnsQuestionRecord;
    CHAR* m_pParsedMessage;
    CString GetDomainName(CString& sCurrentQNAME, PCHAR& pCurrentBufferPoint);
    int m_nParsedMessageLength;
    CString GetCharSTRING(CString& sCurrentCharSTRING, PCHAR& pCurrentBufferPoint);
    CDnsResorceRecord* RemoveFromTail(void);
    unsigned short m_nQuestionCount;
    void AddRRToTail(CDnsResorceRecord* pDnsResorceRecord);

    int GetRestBytes(PCHAR pCurrentBufferPoint, WORD wByteCount)
    {
        return m_nParsedMessageLength - (int)((pCurrentBufferPoint + wByteCount) - m_pParsedMessage);
    }
    CDnsResorceRecord* RemoveFromHeader(void);
    void RemoveRRAt(CDnsResorceRecord* pRemovedRR);
    void PerformQuerySection(PBYTE& rCurrentBufferPosition);
    CDnsMessageWB(
        CDnsMessageWB* pSourceDnsMessage,
        CDnsResorceRecord* pDnsResorceRecord
        );
    UINT32 PerformDnsMessageBuffer(
        PBYTE pMessageBuffer,
        UINT32 nBufferLength
        );
    void DnsReParseResponceMessage(
        DNS_APPROVAL_CONFIG& rApprovalConfig,
        PBYTE pOutputBuffer,
        size_t nOutputBufferLength
        );
    bool DnsQueryParse(
        PDNS_MESSAGE_BUFFER pDnsBuffer,
        WORD wMessageLength,
        DNS_APPROVAL_CONFIG& rApprovalConfig,
        PBYTE pOutputBuffer,
        size_t nOutputBufferLength
        );
    void ParseQuestionSection(
        PCHAR &rCurrentBuffer
        );
    void PerformDomanName(
        CString sDomainName,
        PBYTE pMessageBuffer,
        CDnsResorceRecord* pCurrentRR,
        int& rCurrentMessagePosition
        );
    int FindDomanName(
        CString sDomainName,
        PBYTE pMessageBuffer,
        CDnsResorceRecord* pCurrentRR,
        int nCurrentMessagePosition
        );
    void PerformCharString(
        CString sWCharString,
        PBYTE pMessageBuffer,
        int& rCurrentMessagePosition
        );
    DNS_MESSAGE_BUFFER* m_pSavedQueryMessage;
	void PerformUnpackDomanName(
		CString sDomainName,
		PBYTE pMessageBuffer,
		CDnsResorceRecord* pCurrentRR,
		int& rCurrentMessagePosition
		);
    static CString GetRRTypeName(WORD wRRType);
    CString m_sDnsQuestionTypeName;
    void DumpDnsHeader();
};
